﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SharpShare.Storage.Filter {
    public abstract class FilteredStorageItem : IStorageItem, IEquatable<FilteredStorageItem> {
        protected FilteredStorageItem(IStorageItem baseItem, IStorageFilter filter, IStorageContainer parent) {
            if (baseItem == null) throw new ArgumentNullException("baseItem");
            if (filter == null) throw new ArgumentNullException("filter");

            this.BaseItem = baseItem;
            this.Filter = filter;
            this.Parent = parent;
        }

        public IStorageItem BaseItem { get; private set; }
        public IStorageFilter Filter { get; private set; }

        #region IStorageItem Members

        public string Name {
            get {
                return this.Filter.ModifyName(new FilterScope<IStorageItem>(this.BaseItem, this), this.BaseItem.Name);
            }
        }

        public IStorageContainer Parent {
            get;
            private set;
        }

        public bool Exists {
            get { return this.BaseItem.Exists; }
        }

        public StorageItemAttributes Attributes {
            get {
                return this.BaseItem.Attributes;
            }
            set {
                this.BaseItem.Attributes = value;
            }
        }

        public DateTime DateCreated {
            get {
                return this.BaseItem.DateCreated;
            }
            set {
                this.BaseItem.DateCreated = value;
            }
        }

        public DateTime DateModified {
            get {
                return this.BaseItem.DateModified;
            }
            set {
                this.BaseItem.DateModified = value;
            }
        }

        public IStorageDataProvider OpenMetadata(string name, StorageFileAccess access, StorageFileAccess share, StorageFileMode mode) {
            return this.BaseItem.OpenMetadata(name, access, share, mode);
        }

        bool IStorageItem.RemoveMetadata(string name) {
            return this.BaseItem.RemoveMetadata(name);
        }

        public IEnumerable<string> ListMetadata() {
            return this.BaseItem.ListMetadata();
        }

        public void Delete() {
            this.BaseItem.Delete();
        }

        public void Move(IStorageContainer container, string newNameOrNull) {
            FilteredStorageContainer containerItem = (FilteredStorageContainer)container;
            this.BaseItem.Move(containerItem.BaseItem.DemandContainer(), newNameOrNull);
            this.Parent = containerItem;
        }

        public Security.StorageAccessList AvailableAccess {
            get { return this.BaseItem.AvailableAccess; }
        }

        #endregion

        #region ICastable<IStorageContainer> Members

        IStorageContainer ICastable<IStorageContainer>.TryCast() {
            IStorageContainer baseCasted = this.BaseItem.As<IStorageContainer>();

            if (baseCasted == null) {
                return null;
            }

            return FilteredStorageContainer.Create(baseCasted, this.Filter, this.Parent);
        }

        #endregion

        #region ICastable<IStorageFile> Members

        IStorageFile ICastable<IStorageFile>.TryCast() {
            IStorageFile baseCasted = this.BaseItem.As<IStorageFile>();

            if (baseCasted == null) {
                return null;
            }

            return FilteredStorageFile.Create(baseCasted, this.Filter, this.Parent);
        }

        #endregion

        #region IEquatable<FilteredStorageItem> Members

        public bool Equals(FilteredStorageItem other) {
            if (other == null) {
                return false;
            }

            return (this.BaseItem.Equals(other.BaseItem) && this.Filter.Equals(other.Filter));
        }

        #endregion

        public override bool Equals(object obj) {
            return Equals(obj as FilteredStorageItem);
        }

        public override int GetHashCode() {
            return (this.BaseItem.GetHashCode() ^ this.Filter.GetHashCode());
        }

        public override string ToString() {
            return this.BaseItem.ToString();
        }

        public static FilteredStorageItem Create(IStorageItem item, IStorageFilter filter, IStorageContainer parent) {
            IStorageContainer container = item.As<IStorageContainer>();

            if (container != null) {
                return FilteredStorageContainer.Create(container, filter, parent);
            }

            IStorageFile file = item.As<IStorageFile>();

            if (file != null) {
                return FilteredStorageFile.Create(file, filter, parent);
            }

            return null;
        }
    }
}
